<h1 id="ctypes">C types</h1>

<p>Duktape API uses typedef-wrapped C types almost exclusively to ensure
portability to exotic platforms.  This section provides some background,
summarizes the types, and describes how calling code should use types to
maximize portability.</p>

<p>Portable C/C++ typing is a complex issue, involving:</p>
<ul>
<li>Portable type detection for C99/C++11 and older environments</li>
<li>Bit sizes and ranges of available types, selecting the most appropriate
    types, e.g. fastest or smallest with a guaranteed minimum or exact bit size</li>
<li>Constants for type ranges, such as <code>INT_MIN</code></li>
<li>Format specifiers when types are used in <code>printf()</code> and
    <code>scanf()</code> format strings</li>
</ul>

<p>Duktape only works on platforms with
<a href="http://en.wikipedia.org/wiki/Two's_complement">two's complement</a>
arithmetic.</p>

<h2>Guidelines for code using the Duktape API</h2>

<ul>

<li>Use Duktape types such as <code>duk_idx_t</code> and <code>duk_ret_t</code>
(described below) when declaring variables for maximum portability.  Alternatively
you may use plain types (like <code>long</code>) but your code will be less portable
and you may need to use casts to avoid warnings.  Note that <code>long</code> is a
better default integer type than <code>int</code>, because <code>int</code> may be
only 16 bits wide on some platforms.</li>

<li>Duktape types like <code>duk_int_t</code> have been chosen to be the most
convenient (or fastest) types for the compiler.  If you're using them in
structs whose footprint matters, you may want to use other C types; remember
to check / cast accordingly.</li>

<li>In <code>printf()</code> formatting cast Duktape types to a wide integer
type and use a standard format specific to ensure that the type and the
specifier always match.  For integers, <code>long</code> and <code>unsigned long</code>
are usually a good choice because they don't require C99/C++11 and can usually
hold all integer values used by Duktape typedefs.  For example:
<pre class="c-code">
printf("Result: %ld\n", (long) duk_get_int(ctx, -3));
</pre>
</li>

<li>Duktape API calls which support ANSI C format strings simply pass on the
format string and call arguments to the platform's <code>vsnprintf()</code>
function.  To maximize portability, select format specifiers carefully and
cast arguments to ensure types match.  For example:
<pre class="c-code">
duk_int_t val = 123;
duk_push_sprintf(ctx, "My integer: %ld", (long) val);
</pre>
</li>

<li>A few standard format specifiers:
    <ul>
    <li><code>long</code>: <code>%ld</code></li>
    <li><code>unsigned long</code>: <code>%lu</code></li>
    <li><code>double</code>: <code>%f</code> or <code>%lf</code> for <code>printf()</code>,
        <code>%lf</code> for <code>scanf()</code></li>
    <li><code>size_t</code>: <code>%zu</code> (C99; pre-C99 compilers have various custom specifiers)</li>
    <li><code>intmax_t</code>: <code>%jd</code> (C99)</li>
    <li><code>uintmax_t</code>: <code>%ju</code> (C99)</li>
    </ul>
</li>

<li>Format specifiers used by <code>printf()</code> and <code>scanf()</code>
may be different.  For <code>scanf()</code>, use a standard type and a
standard format code (so that you can be certain they match), then cast
to a Duktape type as necessary.  Again, <code>long</code> and <code>unsigned long</code>
are a good default choice.  For example:
<pre class="c-code">
long val;
sscanf(my_str, "%ld", &amp;val);
duk_push_int(ctx, (duk_int_t) val);
</pre>
</li>

<li>Use the <code>L</code> (or <code>UL</code>) suffix for constants which
are larger than 16 bits to maximize portability.  Like the <code>int</code>
type, integer constants without a suffix are only guaranteed to be 16 bits
wide.  With the <code>L</code> suffix constants are guaranteed to be at least
32 bits wide.  Example:
<pre class="c-code">
duk_push_int(ctx, 1234567L);
</pre>
</li>

<li>Duktape API calls with a filesystem path argument simply pass the
path to <code>fopen()</code>.  There is no way to specify an encoding
or support a wide character set.  To do that, you need to implement a
platform specific helper yourself.</li>

</ul>

<h2>Wrapped types used in the Duktape API</h2>

<p>For the most part you don't need to worry about these type wrappers:
they're intended for exotic environments where some common assumptions
about type bit counts and such don't hold.</p>

<p>The API documentation uses the Duktape wrapped typedef names (such as
<code>duk_idx_t</code>).  The concrete type used by the compiler depends
on your platform and compiler.  When hovering over a prototype in the API
documentation the tool tip will show what concrete types are used when
C99/C++11 types are available and the platform <code>int</code> is at least
32 bits wide (which is nowadays almost always the case).</p>

<p>The following table summarizes a few central typedefs and what the
concrete type selected will be in various (example) environments.  The
table also suggests what plain type you should use for <code>printf()</code>
and <code>scanf()</code> casts for portable formatting/scanning.</p>

<table>
<tr>
<th>Duktape type</th>
<th class="highlight">C99/C++11 32-bit int</th>
<th>Legacy 32-bit int</th>
<th>Legacy 16-bit int</th>
<th><code>printf</code></th>
<th><code>scanf</code></th>
<th>Notes</th>
</tr>
<tr>
<td>duk_int_t</td>
<td class="highlight">int</td>
<td>int</td>
<td>long</td>
<td>%ld<br />long</td>
<td>%ld<br />long</td>
<td>All around integer type, range is [<code>DUK_INT_MIN</code>, <code>DUK_INT_MAX</code>]</td>
</tr>
<tr>
<td>duk_uint_t</td>
<td class="highlight">unsigned int</td>
<td>unsigned int</td>
<td>unsigned long</td>
<td>%lu<br />unsigned long</td>
<td>%lu<br />unsigned long</td>
<td>All around unsigned integer type, range is [0, <code>DUK_UINT_MAX</code>]</td>
</tr>
<tr>
<td>duk_int32_t</td>
<td class="highlight">int32_t</td>
<td>int</td>
<td>long</td>
<td>%ld<br />long</td>
<td>%ld<br />long</td>
<td>Exact type for <code>ToInt32()</code> coercion</td>
</tr>
<tr>
<td>duk_uint32_t</td>
<td class="highlight">uint32_t</td>
<td>unsigned int</td>
<td>unsigned long</td>
<td>%lu<br />unsigned long</td>
<td>%lu<br />unsigned long</td>
<td>Exact type for <code>ToUint32()</code> coercion</td>
</tr>
<tr>
<td>duk_uint16_t</td>
<td class="highlight">uint16_t</td>
<td>unsigned short</td>
<td>unsigned short</td>
<td>%u<br />unsigned int</td>
<td>%u<br />unsigned int</td>
<td>Exact type for <code>ToUint16()</code> coercion</td>
</tr>
<tr>
<td>duk_idx_t</td>
<td class="highlight">int</td>
<td>int</td>
<td>long</td>
<td>%ld<br />long</td>
<td>%ld<br />long</td>
<td>Value stack index</td>
</tr>
<tr>
<td>duk_uarridx_t</td>
<td class="highlight">unsigned int</td>
<td>unsigned int</td>
<td>unsigned long</td>
<td>%lu<br />unsigned long</td>
<td>%lu<br />unsigned long</td>
<td>Ecmascript array index</td>
</tr>
<tr>
<td>duk_codepoint_t</td>
<td class="highlight">int</td>
<td>int</td>
<td>long</td>
<td>%ld<br />long</td>
<td>%ld<br />long</td>
<td>Unicode codepoints</td>
</tr>
<tr>
<td>duk_errcode_t</td>
<td class="highlight">int</td>
<td>int</td>
<td>long</td>
<td>%ld<br />long</td>
<td>%ld<br />long</td>
<td>Integer error codes used in the Duktape API (range for user codes is [1,16777215])</td>
</tr>
<tr>
<td>duk_bool_t</td>
<td class="highlight">int</td>
<td>int</td>
<td>int</td>
<td>%d<br />int</td>
<td>%d<br />int</td>
<td>Boolean return values</td>
</tr>
<tr>
<td>duk_ret_t</td>
<td class="highlight">int</td>
<td>int</td>
<td>int</td>
<td>%d<br />int</td>
<td>%d<br />int</td>
<td>Return value from Duktape/C function</td>
</tr>
<tr>
<td>duk_size_t</td>
<td class="highlight">size_t</td>
<td>size_t</td>
<td>size_t</td>
<td>%lu<br />unsigned long</td>
<td>%lu<br />unsigned long</td>
<td>1:1 mapping now, wrapped for future use.  Range is [0, <code>DUK_SIZE_MAX</code>].
    C99 format specifier is <code>%zu</code>.</td>
</tr>
<tr>
<td>duk_double_t</td>
<td class="highlight">double</td>
<td>double</td>
<td>double</td>
<td>%f or %lf<br />double</td>
<td>%lf<br />double</td>
<td>1:1 mapping now, wrapped for future use, e.g. custom software floating point library.</td>
</tr>
</table>

<h2>Background on C/C++ typing issues</h2>

<p>This section provides some background and rationale for the C typing.</p>

<h3>Bit sizes are not standard (and there's no guaranteed fast 32-bit type)</h3>

<p>Bit sizes of common types like <code>int</code> vary across implementations.
C99/C++11 provide standard integer typedefs like <code>int32_t</code> (exact
signed 32-bit type) and <code>int_fast32_t</code> (fast integer type which
has at least signed 32-bit range).  These typedefs are not available in
older compilers, so platform dependent type detection is necessary.</p>

<p>Duktape needs an integer type which is convenient for the architecture but
still guaranteed to be 32 bits wide.  Such a type is needed to represent array
indices, Unicode points, etc.  However, there is no such standard type and at
least the following variations are seen:</p>
<ul>
<li>a 16-bit <code>int</code> and a 32-bit <code>long</code></li>
<li>a 32-bit <code>int</code> and a 64-bit <code>long</code>, with the 64-bit
    <code>long</code> being inefficient for the processor</li>
<li>a 64-bit <code>int</code> and <code>long</code></li>
</ul>

<p>As can be seen, no built-in C type would be appropriate, so type detection
is needed.  Duktape detects and defines <code>duk_int_t</code> type for these
purposes (at least 32 bits wide, convenient to the CPU).  Normally it is mapped
to <code>int</code> if Duktape can reliably detect that <code>int</code> is 32
bits or wider.  When this is not the case, <code>int_fast32_t</code> is used
if C99 types are available; if C99 is not available, Duktape uses platform
specific detection to arrive at an appropriate type.  The <code>duk_uint_t</code>
is the same but unsigned.  Most other types in the API (such as <code>duk_idx_t</code>)
are mapped to <code>duk_(u)int_t</code> but this may change in the future
if necessary.</p>

<p>Other special types are also needed.  For instance, exactly N bits wide
integers are also needed to ensure proper overflow behavior in some cases.</p>

<h3>Format specifiers</h3>

<p>C/C++ types are often used with <code>printf()</code> and <code>scanf()</code>,
with each type having a format specifier.  The set of format specifiers is only
partially standardized (e.g. <code>%d</code> is used for an <code>int</code>,
regardless of its bit size), but custom codes are sometimes used.</p>

<p>When using type wrappers, the correct format code depends on type detection.
For instance, <code>duk_int_t</code> is mapped to a convenient integer type which is
at least 32 bits wide.  On one platform the underlying type might be <code>int</code>
(format specifier <code>%d</code>) and on another it might be <code>long</code>
(format specifier <code>%ld</code>).  Calling code cannot safely use such a value
in string formatting without either getting the proper format specified from a
preprocessor define or using a fixed format specifier and casting the argument:</p>

<pre class="c-code">
duk_int_t val = /* ... */;

/* Cast value to ensure type and format match.  Selecting the appropriate
 * cast target is problematic, and caller must "play it safe".  Without
 * relying on C99 types, "long" is usually good for signed integers.
 */
printf("value is: %ld\n", (long) val);

/* When assuming C99 types (which limits portability), the maxint_t is
 * guaranteed to represent all signed integers and has a standard format
 * specifiers "%jd".  For unsigned values, umaxint_t and "%ju".
 */
printf("value is: %jd\n", (maxint_t) val);

/* Use a preprocessor define to provide the format code.  Code and format
 * specifier are chosen to match during type detection.
 */
printf(DUK_PRIdINT, val);
</pre>

<p>C99 takes this approach and provides preprocessor defines for C99 types in
<code>inttypes.h</code>.  For instance, the <code>printf()</code> decimal
format specifier for <code>int_fast32_t</code> is <code>PRIdFAST32</code>:</p>

<pre class="c-code">
int_fast32_t val = /* ... */;

printf("value is: " PRIdFAST32 "\n", val);
</pre>

<p>The <code>printf()</code> and <code>scanf()</code> format specifiers may
be different.  One reason is that <code>float</code> arguments are automatically
promoted to <code>double</code> in <code>printf()</code> but they are handled
as distinct types by <code>scanf()</code>.  See
<a href="http://stackoverflow.com/questions/210590/why-does-scanf-need-lf-for-doubles-when-printf-is-okay-with-just-f">why-does-scanf-need-lf-for-doubles-when-printf-is-okay-with-just-f</a>.</p>

<p>The correct format specifier for a <code>double</code> in
<code>printf()</code> is <code>%f</code> (float values are automatically
promoted to doubles) but <code>%lf</code> is also accepted.  The latter is
used in Duktape examples for clarity.  See
<a href="http://stackoverflow.com/questions/4264127/correct-format-specifier-for-double-in-printf">correct-format-specifier-for-double-in-printf</a>.</p>
